package com.csit.util;

import org.apache.log4j.Logger;
import org.mozilla.javascript.Context;
import org.mozilla.javascript.ImporterTopLevel;
import org.mozilla.javascript.NativeJavaObject;
import org.mozilla.javascript.Scriptable;

import java.util.HashMap;
import java.util.Map;

/**
 * User: xpk
 * Date: 2009-9-25
 * Time: 11:37:33
 */
public class JavascriptEvalter {
	private static Logger logger = Logger.getLogger(JavascriptEvalter.class);
	private Scriptable global;
	private Map<String, Object> attributes = new HashMap<String, Object>();

	public JavascriptEvalter() {
		Context cx = Context.enter();
		global = new ImporterTopLevel(cx);
		global.put("_this", global, Context.toObject(this, global));
		Context.exit();
	}

	public String eval(String script) {
		Object o = evalObject(script);
		return o != null ? o.toString() : null;
	}

	public Object evalObject(String script) {
		logger.debug("eval script:\n" + script);
		Context cx = Context.enter();
		try {
			Object retval;
			cx.setOptimizationLevel(-1);
			cx.setGeneratingDebug(false);
			cx.setGeneratingSource(false);
			cx.setOptimizationLevel(0);
			cx.setDebugger(null, null);
			retval = cx.evaluateString(global, script, null, -1, null);
			if (retval != null) {
				if (retval instanceof NativeJavaObject)
					retval = ((NativeJavaObject) retval).unwrap();
			}
			logger.debug(retval);
			return retval == null ? null : retval;
		} finally {
			Context.exit();
		}
	}

	public void addGlobalObject(String varName, Object varObject) {
		global.put(varName, global, Context.toObject(varObject, global));
	}

	public Map<String, Object> getAttributes() {
		return attributes;
	}

	public void setAttributes(Map<String, Object> attributes) {
		this.attributes = attributes;
	}

	public void setAttribute(String key, Object obj) {
		this.attributes.put(key, obj);
	}

	public Object getAttribute(String key) {
		return this.attributes.get(key);
	}

	public Scriptable getGlobal() {
		return global;
	}
}

